/*
 * Copyright 2012 Alain Pannetrat (L1L1@gmx.com)
 * 
 * This file is part of cookie-miner.
 * 
 * cookie-miner is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * cookie-miner is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License 
 * along with cookie-miner. If not, see http://www.gnu.org/licenses/.
 *
 * @version: $Id$
 *
 */
#ifndef _VECTORS_H_
#define _VECTORS_H_

#include <math.h>

#define VFloat float

class Vector {
	public:
		static const Vector null;

		//Vector() {}

		Vector(VFloat f=0);

		Vector(VFloat init_k0, VFloat init_k1, VFloat init_k2);

		//Vector(const Vector&v);
		//const Vector& operator=(const Vector&v);
		//~Vector();

		bool from_string(const char *str); 

		VFloat abs_square() const;

		VFloat norm() const; 

		VFloat operator[](unsigned i) const;

		VFloat& operator[](unsigned i);

		const Vector& negate();

		const Vector& operator+=(const Vector& v);
		
		const Vector& operator-=(const Vector& v);
		
		const Vector& operator*=(VFloat f);

		friend inline bool operator==(const Vector& a, const Vector& b);

		friend inline const Vector operator+(const Vector &a, const Vector &b);

		friend inline const Vector operator-(const Vector &a, const Vector &b); 

		friend inline const Vector operator*(VFloat f, const Vector &a);

		friend inline const Vector operator*(const Vector &a, VFloat f);

	private:
		VFloat k[3];
};

/********************************************************************
 * INLINED DECLARATIONS 
 */

inline Vector::Vector(VFloat f) 
{
	k[0] = k[1] = k[2] = f; 
}

inline Vector::Vector(VFloat init_k0, VFloat init_k1, VFloat init_k2) 
{ 
	k[0]=init_k0; 
	k[1]=init_k1; 
	k[2]=init_k2;
}

inline VFloat Vector::abs_square() const 
{
	return k[0]*k[0]+k[1]*k[1]+k[2]*k[2];
}

inline VFloat Vector::norm() const 
{
	return sqrt(k[0]*k[0]+k[1]*k[1]+k[2]*k[2]); 
}			

inline VFloat Vector::operator[](unsigned i) const 
{ 
	return k[i];
}

inline VFloat& Vector::operator[](unsigned i) 
{ 
	return k[i];
}

inline const Vector& Vector::negate() 
{ 
	k[0]=-k[0]; 
	k[1]=-k[1]; 
	k[2]=-k[2]; 
	return *this; 
}


inline const Vector& Vector::operator+=(const Vector& v)
{
	k[0] += v.k[0]; 
	k[1] += v.k[1]; 
	k[2] += v.k[2];
	return *this;
}

inline const Vector& Vector::operator-=(const Vector& v)
{
	k[0] -= v.k[0]; 
	k[1] -= v.k[1]; 
	k[2] -= v.k[2];
	return *this;
}

inline const Vector& Vector::operator*=(VFloat f)
{
	k[0] *= f;
	k[1] *= f;
	k[2] *= f;
	return *this;
}


inline bool operator==(const Vector& a, const Vector& b) 
{
    return a.k[0]==b.k[0] && 
	   a.k[1]==b.k[1] && 
	   a.k[2]==b.k[2];
}

inline const Vector operator+(const Vector &a, const Vector &b) 
{
	return Vector(a.k[0]+b.k[0],
			a.k[1]+b.k[1],
			a.k[2]+b.k[2]);
}

inline const Vector operator-(const Vector &a, const Vector &b) 
{
	return Vector(a.k[0]-b.k[0],
			a.k[1]-b.k[1],
			a.k[2]-b.k[2]);
}

inline const Vector operator*(VFloat f, const Vector &a)
{
    	return Vector(f*a.k[0],f*a.k[1],f*a.k[2]);
}

inline const Vector operator*(const Vector &a, VFloat f)
{
    	return Vector(f*a.k[0],f*a.k[1],f*a.k[2]);
}

#endif
